home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Floppyshop 2
/
Floppyshop - 2.zip
/
Floppyshop - 2.iso
/
art&graf.ix
/
art-0039
/
source
/
dcpiccnv.mod
< prev
next >
Wrap
Text File
|
1997-04-16
|
25KB
|
639 lines
IMPLEMENTATION MODULE DCPicCnv;
(*---------------------------------------------------------------------*)
(* LOW LEVEL Picture Conversion Routines For DegasConvert *)
(* *)
(* *)
(* The reason I choose to split the conversion routines is because *)
(* the higher level routines need to access the screen to show the *)
(* user what is happening. This way the low-level conversion *)
(* module doesn't need to know about the screen, this hides *)
(* implentation details. *)
(* *)
(* Note: There are functions for each type of resolution, this is *)
(* for efficiency reasons. Also for efficiency reasons there *)
(* will be routines to convert ONE picture line. The picture *)
(* to be operated on will be passed each time along with the *)
(* print palette to go with it. *)
(* *)
(* The first version of this program was rather simple in the way it *)
(* allocated black and white patterns to the colours in the picture *)
(* to be converted. Specifically, it just used the bits in the index *)
(* number of a pixel as the pattern to plot.( i.e. a dark colour may *)
(* come out light in the conversion ). A better way would be to look *)
(* at the colours in the palette and allocate a shade to it depending*)
(* on the intensity of the colour of the pixel. This is what is *)
(* implemented in this version of the program. *)
(* *)
(* For a low-res picture there are 16 colours of different intensity *)
(* spread through the palette. I want to allocate print bit patterns *)
(* ( a number from 0 to 15 ) to each entry in the palette so that *)
(* light colours print light and dark colours print dark. To *)
(* simplify(!) this process I intend to sort the palette by *)
(* intensity, allocate the print patterns to the palette in order *)
(* of increasing number of on-bits in the print bit pattern. *)
(* *)
(* Degas Picture Functions: *)
(* 1) Return the colour index of pixel *)
(* 2) Return the Red,Green,Blue components of a palette entry *)
(* 3) Assign a print bit pattern,got from user,to a palette entry *)
(* 4) Assign Default print bit patterns to the picture palette *)
(* 5) Return the print bit pattern for a pixel *)
(* 6) Set a pixel in the hi-res picture *)
(* 7) Toggle a pixel in the hi-res picture *)
(* 8) Clear all pixels in the hi-res picture *)
(* *)
(* 22/ 8/89 LGM Change routines to use pointers to PixelGroups. *)
(* *)
(* *)
(* *)
(* Version 1.1 August 1987 L.G.Miller *)
(*---------------------------------------------------------------------*)
(* IMPORT Trace; *)
FROM DCGlobal IMPORT LowRes, (* constants *)
LowResMaxX,
LowResMaxY,
LowResNoPlanes,
MedRes,
MedResMaxX,
MedResMaxY,
MedResNoPlanes,
HiRes,
HiResMaxX,
HiResMaxY,
HiResNoPlanes,
Palette, (* types *)
BitPlanesEnum,
LowRes16Pixels,
LowResScreenLine,
LowResScreen,
LowResPixelGroupPtr,
LowResScreenLinePtr,
MedRes16Pixels,
MedResScreenLine,
MedResScreen,
MedResPixelGroupPtr,
MedResScreenLinePtr,
HiRes16Pixels,
HiResScreenLine,
HiResScreen,
HiResPixelGroupPtr,
HiResScreenLinePtr,
DegasPicture,
PrintPalette,
PrintBitPatternSet,
PaletteEntry,
BITSPERWORD;
FROM QSort IMPORT SortArrayWithKeys;
IMPORT DCQPicCnv;
FROM IntLogic IMPORT IAND, RS;
FROM SYSTEM IMPORT ADR,
ADDRESS, LONGWORD, WORD;
TYPE
PaletteEntryPtr = POINTER TO PaletteEntry;
CONST
CLongOne = LONGCARD(1);
(*----------------------------------------------------------------------*)
(* Utility routines for the implementation of Setting Default Palette *)
(* *)
(* The brighter the colour the lighter the print should be. Bright *)
(* colours should be sorted to the 'top' of the array. *)
(* *)
(* The cubing of the components gives weighting to the INTENSITY of the *)
(* component. If something like this were not done the the colour 3,3,3 *)
(* would by brighter than 5,0,0. This would be wrong; try it and see! *)
(*----------------------------------------------------------------------*)
PROCEDURE CompareColours( PE1Ptr, PE2Ptr : PaletteEntryPtr ) : BOOLEAN;
CONST CMaxColour = 7 * 7 * 7 * 3 + 1;
VAR colour1, colour2 : CARDINAL;
BEGIN
WITH PE1Ptr^ DO
colour1 := CMaxColour -
( ( RedComponent * RedComponent * RedComponent )
+ ( GreenComponent * GreenComponent * GreenComponent )
+ ( BlueComponent * BlueComponent * BlueComponent ) )
END; (* with *)
WITH PE2Ptr^ DO
colour2 := CMaxColour -
( ( RedComponent * RedComponent * RedComponent )
+ ( GreenComponent * GreenComponent * GreenComponent )
+ ( BlueComponent * BlueComponent * BlueComponent ) )
END; (* with *)
RETURN ( colour1 < colour2 );
END CompareColours;
PROCEDURE SortByColour ( VAR ppalette : PrintPalette; nitems : CARDINAL );
BEGIN
SortArrayWithKeys(ppalette, ppalette[0], LONG(nitems), CompareColours );
END SortByColour;
PROCEDURE CompareIndex( PE1Ptr, PE2Ptr : PaletteEntryPtr ) : BOOLEAN;
BEGIN
RETURN ( PE1Ptr^.ColourIndex < PE2Ptr^.ColourIndex );
END CompareIndex;
PROCEDURE SortByIndex ( VAR ppalette : PrintPalette; nitems : CARDINAL );
BEGIN
SortArrayWithKeys(ppalette, ppalette[0], LONG(nitems), CompareIndex );
END SortByIndex;
PROCEDURE LowRes16PixelsAddr ( x, y : CARDINAL;
VAR picture : LowResScreen;
VAR PixelNo : CARDINAL;
VAR PGPtr : LowRes16PixelsPtr );
VAR gno : CARDINAL;
BEGIN
PixelNo := x MOD BITSPERWORD;
gno := x DIV BITSPERWORD;
PGPtr := ADR( picture[y][gno] );
END LowRes16PixelsAddr;
PROCEDURE MedRes16PixelsAddr ( x, y : CARDINAL;
VAR picture : MedResScreen;
VAR PixelNo : CARDINAL;
VAR PGPtr : MedRes16PixelsPtr );
VAR gno : CARDINAL;
BEGIN
PixelNo := x MOD BITSPERWORD;
gno := x DIV BITSPERWORD;
PGPtr := ADR( picture[y][gno] );
END MedRes16PixelsAddr;
PROCEDURE HiRes16PixelsAddr ( x, y : CARDINAL;
VAR picture : HiResScreen;
VAR PixelNo : CARDINAL;
VAR PGPtr : HiRes16PixelsPtr );
VAR gno : CARDINAL;
BEGIN
PixelNo := x MOD BITSPERWORD;
gno := x DIV BITSPERWORD;
PGPtr := ADR( picture[y][gno] );
END HiRes16PixelsAddr;
(*----------------------------------------------------------------------*)
(* Find out the Colour index of a low-res pixel. *)
(*----------------------------------------------------------------------*)
PROCEDURE QueryXYLowResPixelIndex( x, y : CARDINAL;
Picture : DegasPicture ) : CARDINAL;
VAR
LowResPGPtr : LowRes16PixelsPtr;
LowResPixelNo : CARDINAL;
BEGIN
LowRes16PixelsAddr( x, y, Picture.LowResPicture,
LowResPixelNo, LowResPGPtr);
RETURN QueryLowResPixelIndex(LowResPixelNo, LowResPGPtr);
END QueryXYLowResPixelIndex;
(*----------------------------------------------------------------------*)
(* Split colour value into its red, green and blue components. *)
(*----------------------------------------------------------------------*)
PROCEDURE ColourComponents ( colour : CARDINAL;
VAR red, green, blue : CARDINAL );
CONST
CRightShift = 4; (* shift 1 nibble right *)
CColourComponentMask = 7; (* Least Sig. 3 bits *)
BEGIN
blue := IAND(colour, CColourComponentMask);
colour := RS(colour, CRightShift);
green := IAND(colour, CColourComponentMask);
colour := RS(colour, CRightShift);
red := IAND(colour, CColourComponentMask);
END ColourComponents;
(*----------------------------------------------------------------------*)
(* Get red, green, blue components of a low-res pixel *)
(*----------------------------------------------------------------------*)
PROCEDURE QueryLowResPixelColour ( PixelNo : CARDINAL;
PGPtr : LowRes16PixelsPtr;
VAR palette : Palette;
VAR red, green, blue : CARDINAL );
VAR i, colour : CARDINAL;
BEGIN
i := DCQPicCnv.QQryLRPIndex( PixelNo, PGPtr ); (* get colour index *)
colour := palette[i]; (* bits = XXXX XRRR XGGG XBBB *)
DCQPicCnv.QQColourComp( colour, red, green, blue );
END QueryLowResPixelColour;
(*----------------------------------------------------------------------*)
(* Get the colour index of a low-res pixel *)
(*----------------------------------------------------------------------*)
PROCEDURE QueryLowResPixelIndex ( PixelNo : CARDINAL;
PGPtr : LowRes16PixelsPtr ) : CARDINAL;
(*
CONST
CPlane1Index = 1;
CPlane2Index = 2;
CPlane3Index = 4;
CPlane4Index = 8;
VAR index : CARDINAL;
*)
BEGIN
(*
index := 0;
IF ( PixelNo IN PGPtr^[BitPlane1]) THEN
INC(index,CPlane1Index);
END;
IF ( PixelNo IN PGPtr^[BitPlane2]) THEN
INC(index,CPlane2Index);
END;
IF ( PixelNo IN PGPtr^[BitPlane3]) THEN
INC(index,CPlane3Index);
END;
IF ( PixelNo IN PGPtr^[BitPlane4]) THEN
INC(index,CPlane4Index);
END;
RETURN index;
*)
RETURN DCQPicCnv.QQryLRPIndex( PixelNo, PGPtr );
END QueryLowResPixelIndex;
(*----------------------------------------------------------------------*)
(* Get the Print bit pattern associated with a low-res pixel *)
(* *)
(* The print-palette is in colour index order *)
(*----------------------------------------------------------------------*)
PROCEDURE QueryLowResPixelPBPattern ( PixelNo : CARDINAL;
PGPtr : LowRes16PixelsPtr;
VAR printpalette : PrintPalette;
VAR pbp : PrintBitPatternSet );
VAR
colourindex : CARDINAL;
BEGIN
colourindex := QueryLowResPixelIndex(PixelNo, PGPtr);
pbp := printpalette[colourindex].PrintBitPattern;
END QueryLowResPixelPBPattern;
(*----------------------------------------------------------------------*)
(* medium res versions of the query pixel routines *)
(*----------------------------------------------------------------------*)
(*----------------------------------------------------------------------*)
(* Find out the Colour index of a med-res pixel. *)
(*----------------------------------------------------------------------*)
PROCEDURE QueryXYMedResPixelIndex( x, y : CARDINAL;
Picture : DegasPicture ) : CARDINAL;
VAR
MedResPGPtr : MedRes16PixelsPtr;
MedResPixelNo : CARDINAL;
BEGIN
MedRes16PixelsAddr( x, y, Picture.MedResPicture,
MedResPixelNo, MedResPGPtr);
RETURN QueryMedResPixelIndex(MedResPixelNo, MedResPGPtr);
END QueryXYMedResPixelIndex;
PROCEDURE QueryMedResPixelColour ( PixelNo : CARDINAL;
PGPtr : MedRes16PixelsPtr;
VAR palette : Palette;
VAR red, green, blue : CARDINAL );
VAR i, colour : CARDINAL;
BEGIN
i := QueryMedResPixelIndex( PixelNo, PGPtr ); (* get colour index *)
colour := palette[i]; (* bits = XXXX XRRR XGGG XBBB *)
DCQPicCnv.QQColourComp( colour, red, green, blue );
END QueryMedResPixelColour;
PROCEDURE QueryMedResPixelIndex ( PixelNo : CARDINAL;
PGPtr : MedRes16PixelsPtr ) : CARDINAL;
(*
CONST
CPlane1Index = 1;
CPlane2Index = 2;
VAR index : CARDINAL;
*)
BEGIN
(*
index := 0;
IF ( PixelNo IN PGPtr^[BitPlane1]) THEN
INC(index,CPlane1Index);
END;
IF ( PixelNo IN PGPtr^[BitPlane2]) THEN
INC(index,CPlane2Index);
END;
RETURN index;
*)
RETURN DCQPicCnv.QQryMRPIndex( PixelNo, PGPtr );
END QueryMedResPixelIndex;
PROCEDURE QueryMedResPixelPBPattern ( PixelNo : CARDINAL;
PGPtr : MedRes16PixelsPtr;
VAR printpalette : PrintPalette;
VAR pbp : PrintBitPatternSet );
VAR
colourindex : CARDINAL;
BEGIN
colourindex := QueryMedResPixelIndex(PixelNo, PGPtr);
pbp := printpalette[colourindex].PrintBitPattern;
END QueryMedResPixelPBPattern;
(*----------------------------------------------------------------------*)
(* Change the BitPattern printed for a colour index. *)
(*----------------------------------------------------------------------*)
PROCEDURE SetPBPattern ( VAR printpalette : PrintPalette;
colourindex : CARDINAL;
pbp : PrintBitPatternSet );
BEGIN
printpalette[colourindex].PrintBitPattern := pbp;
END SetPBPattern;
(*----------------------------------------------------------------------*)
(* Return the Bit Pattern to be printed for a particular colour *)
(*----------------------------------------------------------------------*)
PROCEDURE QueryPBPattern ( VAR printpalette : PrintPalette;
colourindex : CARDINAL;
VAR pbp : PrintBitPatternSet );
BEGIN
pbp := printpalette[colourindex].PrintBitPattern;
END QueryPBPattern;
(*----------------------------------------------------------------------*)
(*----------------------------------------------------------------------*)
(* Routines to process the output hi-res picture *)
(*----------------------------------------------------------------------*)
(*----------------------------------------------------------------------*)
(*----------------------------------------------------------------------*)
(* Reset all the pixels in the output hi-res picture *)
(*----------------------------------------------------------------------*)
PROCEDURE ClearHiRes ( VAR screen : HiResScreen );
CONST CMaxGroup = HiResMaxX DIV BITSPERWORD;
VAR HiPGPtr : HiRes16PixelsPtr;
ngroups : CARDINAL;
pixno : CARDINAL;
x, y : CARDINAL;
BEGIN
HiRes16PixelsAddr( 0, 0, screen, pixno, HiPGPtr );
FOR y := 0 TO HiResMaxY DO
FOR x := 0 TO CMaxGroup DO
HiPGPtr^ := {};
HiPGPtr := ADDRESS(LONGCARD(HiPGPtr) + SIZE(HiPGPtr^));
END;
END;
END ClearHiRes;
PROCEDURE SetHiResPixel ( PixelNo : CARDINAL;
PGPtr : HiRes16PixelsPtr );
BEGIN
INCL( PGPtr^, PixelNo );
END SetHiResPixel;
(*----------------------------------------------------------------------*)
(* This routine will plot the pattern in a square. *)
(*----------------------------------------------------------------------*)
PROCEDURE SetLowToHiResPBPattern ( x, y : CARDINAL;
VAR screen : HiResScreen;
pbp : PrintBitPatternSet );
VAR i : CARDINAL;
BEGIN (*
IF ( 0 IN pbp ) THEN SetHiResPixel( x, y, screen ); END;
IF ( 1 IN pbp ) THEN SetHiResPixel( x+1, y, screen ); END;
IF ( 2 IN pbp ) THEN SetHiResPixel( x, y+1, screen ); END;
IF ( 3 IN pbp ) THEN SetHiResPixel( x+1, y+1, screen ); END;
*)
END SetLowToHiResPBPattern;
(*----------------------------------------------------------------------*)
(* This routine will plot the pattern in a square. OPTIMIZED VERSION *)
(* *)
(* Assumptions: The pattern to be set will fit in one hires 16 pixel grp*)
(*----------------------------------------------------------------------*)
PROCEDURE OptSetLowToHiResPBPattern ( StartBitno : CARDINAL;
VAR ScreenLine1 : HiRes16PixelsPtr;
VAR ScreenLine2 : HiRes16PixelsPtr;
VAR pbp : PrintBitPatternSet);
BEGIN
IF ( 0 IN pbp ) THEN (* SetHiResPixel( x, y, screen ); *)
INCL( ScreenLine1^, StartBitno );
END;
IF ( 2 IN pbp ) THEN (* SetHiResPixel( x, y+1, screen ); *)
INCL( ScreenLine2^, StartBitno );
END;
INC(StartBitno);
IF ( 1 IN pbp ) THEN (* SetHiResPixel( x+1, y, screen ); *)
INCL( ScreenLine1^, StartBitno );
END;
IF ( 3 IN pbp ) THEN (* SetHiResPixel( x+1, y+1, screen ); *)
INCL( ScreenLine2^, StartBitno );
END;
END OptSetLowToHiResPBPattern;
(*----------------------------------------------------------------------*)
(* This routine will plot the pattern in a rectangle *)
(*----------------------------------------------------------------------*)
PROCEDURE SetMedToHiResPBPattern ( x, y : CARDINAL;
VAR screen : HiResScreen;
pbp : PrintBitPatternSet );
BEGIN (*
IF ( 0 IN pbp ) THEN SetHiResPixel( x, y, screen ); END;
IF ( 1 IN pbp ) THEN SetHiResPixel( x, y+1, screen ); END;
*)
END SetMedToHiResPBPattern;
(*----------------------------------------------------------------------*)
(* This routine will plot the pattern in a rectangle - OPTIMIZED VERSION*)
(*----------------------------------------------------------------------*)
PROCEDURE OptSetMedToHiResPBPattern ( StartBitno : CARDINAL;
VAR ScreenLine1 : HiRes16PixelsPtr;
VAR ScreenLine2 : HiRes16PixelsPtr;
VAR pbp : PrintBitPatternSet);
BEGIN
IF ( 0 IN pbp ) THEN (* SetHiResPixel( x, y, screen ); *)
INCL( ScreenLine1^, StartBitno );
END;
IF ( 1 IN pbp ) THEN (* SetHiResPixel( x, y+1, screen ); *)
INCL( ScreenLine2^, StartBitno );
END;
END OptSetMedToHiResPBPattern;
(*----------------------------------------------------------------------*)
(* Optimized, a bit... *)
(*----------------------------------------------------------------------*)
PROCEDURE ConvertLowToHiResOneLine ( VAR inpic, outpic : DegasPicture;
VAR printpalette : PrintPalette;
inlineno : CARDINAL );
CONST CMaxLowResGroup = LowResMaxX DIV BITSPERWORD;
VAR HiResPG1Ptr,
HiResPG2Ptr : HiRes16PixelsPtr;
HiResPixelNo : CARDINAL;
LowResPGPtr : LowRes16PixelsPtr;
LowResPixelNo : CARDINAL;
LowResPixelGroup,
colour : CARDINAL;
BEGIN
LowRes16PixelsAddr( 0, inlineno, inpic.LowResPicture,
LowResPixelNo, LowResPGPtr);
HiRes16PixelsAddr( 0, (inlineno * 2), outpic.HiResPicture,
HiResPixelNo, HiResPG1Ptr);
HiResPG2Ptr := ADDRESS(LONGCARD(HiResPG1Ptr)
+ SIZE(outpic.HiResPicture[0]));
FOR LowResPixelGroup := 0 TO CMaxLowResGroup DO
HiResPixelNo := 0;
FOR LowResPixelNo := 0 TO BITSPERWORD-1 DO
colour := QueryLowResPixelIndex( LowResPixelNo, LowResPGPtr );
(* used to be OptSetLowToHiResPBPattern( ... *)
DCQPicCnv.QSetLTHPBP ( HiResPixelNo,
HiResPG1Ptr,
HiResPG2Ptr,
printpalette[colour].PrintBitPattern);
INC(HiResPixelNo, 2);
IF HiResPixelNo > BITSPERWORD-1 THEN
HiResPixelNo := 0;
HiResPG1Ptr := ADDRESS(LONGCARD(HiResPG1Ptr)+SIZE(HiResPG1Ptr^));
HiResPG2Ptr := ADDRESS(LONGCARD(HiResPG2Ptr)+SIZE(HiResPG1Ptr^));
END;
END; (* for *)
LowResPGPtr := ADDRESS(LONGCARD(LowResPGPtr)+SIZE(LowResPGPtr^));
END; (* for *)
END ConvertLowToHiResOneLine;
(*----------------------------------------------------------------------*)
(* Optimized, a bit... *)
(*----------------------------------------------------------------------*)
PROCEDURE ConvertMedToHiResOneLine ( VAR inpic, outpic : DegasPicture;
VAR printpalette : PrintPalette;
inlineno : CARDINAL );
CONST CMaxMedResGroup = MedResMaxX DIV BITSPERWORD;
VAR HiResPG1Ptr,
HiResPG2Ptr : HiRes16PixelsPtr;
HiResPixelNo : CARDINAL;
MedResPGPtr : MedRes16PixelsPtr;
MedResPixelNo : CARDINAL;
MedResPixelGroup,
colour : CARDINAL;
BEGIN
MedRes16PixelsAddr( 0, inlineno, inpic.MedResPicture,
MedResPixelNo, MedResPGPtr);
HiRes16PixelsAddr( 0, (inlineno * 2), outpic.HiResPicture,
HiResPixelNo, HiResPG1Ptr);
HiResPG2Ptr := ADDRESS(LONGCARD(HiResPG1Ptr)
+ SIZE(outpic.HiResPicture[0]));
FOR MedResPixelGroup := 0 TO CMaxMedResGroup DO
HiResPixelNo := 0;
FOR MedResPixelNo := 0 TO BITSPERWORD-1 DO
colour := QueryMedResPixelIndex( MedResPixelNo, MedResPGPtr );
(* used to be OptSetMedToHiResPBPattern( ... *)
DCQPicCnv.QSetMTHPBP ( HiResPixelNo,
HiResPG1Ptr,
HiResPG2Ptr,
printpalette[colour].PrintBitPattern);
INC(HiResPixelNo, 1);
IF HiResPixelNo > BITSPERWORD-1 THEN
HiResPixelNo := 0;
HiResPG1Ptr := ADDRESS(LONGCARD(HiResPG1Ptr)+SIZE(HiResPG1Ptr^));
HiResPG2Ptr := ADDRESS(LONGCARD(HiResPG2Ptr)+SIZE(HiResPG1Ptr^));
END;
END; (* for *)
MedResPGPtr := ADDRESS(LONGCARD(MedResPGPtr)+SIZE(MedResPGPtr^));
END; (* for *)
END ConvertMedToHiResOneLine;
END DCPicCnv.